package com.yonyou.pmclouds.plan.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.annotation.Insert;
import com.yonyou.pmclouds.basecom.entity.SuperVO;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.exception.IllegalRequestArgException;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.basecom.util.CommonFieldConst;
import com.yonyou.pmclouds.outter.user.UserInfoQuery;
import com.yonyou.pmclouds.plan.entity.*;
import com.yonyou.pmclouds.plan.rmiitf.ProjectPlanMaintain;
import com.yonyou.pmclouds.plan.rmiitf.ProjectPlanQuery;
import com.yonyou.pmclouds.project.entity.ProjectVO;
import com.yonyou.pmclouds.project.rmiitf.ProjectSimpleQuery;
import com.yonyou.pmclouds.workflow.aspect.PMApprove;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@RestController
@RequestMapping({"/mobile/plan", "/plan"})
@Deprecated
public class ProjectPlanController {
    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private ProjectPlanMaintain maintain;
    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private ProjectPlanQuery query;
    @Autowired
    private UserInfoQuery userInfoQuery;
    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private ProjectSimpleQuery projectSimpleQuery;

    private static final String HAS_PLAN = "hasPlan";
    private static final String MY_PLAN = "myPlan";
    private static final String ALL_PLAN = "allPlan";

    @Insert
    @PostMapping("/insert")
    public ProjectPlanVO insertPlan(@RequestBody @Validated(ProjectPlanVO.InsertValid.class) ProjectPlanVO plan, BindingResult errors) throws BusinessException {
        if (errors.hasErrors()) {
            throw new IllegalRequestArgException();
        }
        String pk = maintain.insertPlan(plan);
        return this.queryPlan(pk);
    }

    @PostMapping("/addDefault")
    @PMApprove(trigger = "save")
    public ProjectPlanVO addDefault(@RequestBody ProjectPlanVO projectPlanVO) throws BusinessException {

        projectPlanVO = maintain.addDefaultPorjetPlan(projectPlanVO);

        return projectPlanVO;
    }

    @PostMapping("/update")
    public ProjectPlanVO updatePlan(@RequestBody @Validated(ProjectPlanVO.UpdateValid.class) ProjectPlanVO plan, BindingResult errors) throws BusinessException {
        if (errors.hasErrors()) {
            throw new IllegalRequestArgException();
        }
        String pk = maintain.updatePlan(plan);
        return this.queryPlan(pk);
    }


    public ProjectPlanVO queryPlan(@RequestParam("id") String id) throws BusinessException {
        ProjectPlanVO plan = query.queryPlanByIdWithPic(id);
        // 翻译前置计划
        if (plan != null && plan.getDependPlan() != null) {
            ProjectPlanVO dependPlan = query.queryPlanById(plan.getDependPlan());
            if (dependPlan != null) {
                plan.setDependPlanName(dependPlan.getSname());
            }
        }
        return plan;
    }

    @GetMapping("/get")
    public ProjectPlanViewVO queryPlanView(@RequestParam("id") String id) throws BusinessException {
        ProjectPlanVO plan = this.queryPlan(id);
        if (plan == null) {
            return null;
        }
        ProjectPlanViewVO view = ProjectPlanViewVO.convertVO(plan);
        PlanProgressVO prog = query.queryProgress(plan.getPkPlan());
        if (prog != null) {
            view.setProgress(prog.getProgress());
            view.setFirstSubmitDate(prog.getFirstSubmitDate());
            view.setLastSubmitDate(prog.getLastSubmitDate());
            view.setStartDate(prog.getStartDate());
            view.setEndDate(prog.getEndDate());
            if (view.getStartDate() != null) {
                view.setExecuteStartDate(view.getStartDate());
            } else {
                view.setExecuteStartDate(view.getFirstSubmitDate());
            }
            if (view.getEndDate() != null) {
                view.setExecuteEndDate(view.getEndDate());
            } else {
                view.setExecuteEndDate(view.getLastSubmitDate());
            }
        }
        return view;
    }

    @GetMapping("/project")
    public ProjectPlanViewVO[] queryProject(@RequestParam("projectId") String projectId) throws BusinessException {
        ProjectPlanViewVO[] allVOs = query.queryViewByProject(projectId);
        if (ArrayUtils.isEmpty(allVOs)) {
            return allVOs;
        }
        Map<String, List<ProjectPlanViewVO>> childMap = genChildMap(allVOs);

        List<ProjectPlanViewVO> result = childMap.get(StringUtils.EMPTY);
        if (result == null) {
            return new ProjectPlanViewVO[0];
        } else {
            genCodeOfTree(null, result, childMap);
            return result.toArray(new ProjectPlanViewVO[0]);
        }
        // TODO 是否要考虑数据量超大的情况
    }

    /**
     * @param projectId
     * @return App端我的任务和全部计划数据
     * @throws BusinessException
     */
    @GetMapping("/getProjectPlanData")
    public Map getProjectPlanData(@RequestParam("projectId") String projectId) throws BusinessException {
        HashMap<String, Object> data = new HashMap<>();

        ProjectPlanViewVO[] allVOs = query.queryViewByProject(projectId);
        if (ArrayUtils.isEmpty(allVOs)) {
            //当前项目没有计划
            data.put(HAS_PLAN, false);
            data.put(MY_PLAN, null);
            data.put(ALL_PLAN, null);
            return data;
        }
        Map<String, List<ProjectPlanViewVO>> childMap = genChildMap(allVOs);

        List<ProjectPlanViewVO> result = childMap.get(StringUtils.EMPTY);

        if (result == null) {
            data.put(HAS_PLAN, false);
            data.put(MY_PLAN, null);
            data.put(ALL_PLAN, null);
            return data;
        } else {

            ProjectVO projectVO = projectSimpleQuery.queryProject(projectId);
            String userId = RuntimeEnvironment.getLoginUserId();
            //userId = "e2df3b10-97d7-4e03-8dfe-dd816942a253";
            genCodeOfTree(null, result, childMap);
            //计算进度
            setProcess(null, result);
            //设置负责人flag
            setNoManagerFlag(null, result);
            //筛选我的任务
            List<ProjectPlanViewVO> lastProjectPlanVO = getLastProjectPlanVO(userId, null, result, null, true);
            //筛选全部计划
            List<ProjectPlanViewVO> projectPlanVOTree = getProjectPlanVOTree(userId, null, result, null, true);
            data.put(HAS_PLAN, true);
            data.put(MY_PLAN, lastProjectPlanVO);
            if (!StringUtils.isEmpty(projectVO.getManager()) && userId.equals(projectVO.getManager())) {
                data.put(ALL_PLAN, result);
            } else {
                data.put(ALL_PLAN, projectPlanVOTree);
            }
            return data;
        }
    }


    private Map<String, List<ProjectPlanViewVO>> genChildMap(ProjectPlanViewVO[] allVOs) {
        // 构造树
        Map<String, List<ProjectPlanViewVO>> childMap = new HashMap<>();
        for (ProjectPlanViewVO vo : allVOs) {
            String parent = vo.getPkParent();
            if (StringUtils.isEmpty(parent)) {
                parent = StringUtils.EMPTY;
            }
            List<ProjectPlanViewVO> children = childMap.get(parent);
            if (children == null) {
                children = new ArrayList<>();
                childMap.put(parent, children);
            }
            children.add(vo);
        }
        for (ProjectPlanViewVO vo : allVOs) {
            vo.setScode(null);
        }
        for (ProjectPlanViewVO vo : allVOs) {
            List<ProjectPlanViewVO> children = childMap.get(vo.getPkPlan());
            if (children != null) {
                vo.setChild(children.toArray(new ProjectPlanViewVO[0]));
            }
        }

        return childMap;
    }

    private void genCodeOfTree(ProjectPlanViewVO parent, List<ProjectPlanViewVO> tree, Map<String, List<ProjectPlanViewVO>> childMap) {
        for (ProjectPlanViewVO plan : tree) {
            if (parent == null) {
                plan.setScode(Integer.toString(plan.getSeq()));
            } else {
                plan.setScode(parent.getScode() + '.' + plan.getSeq());
            }
            List<ProjectPlanViewVO> children = childMap.get(plan.getPkPlan());
            if (children != null && !children.isEmpty()) {
                // 递归应该不会出问题，最深20层
                genCodeOfTree(plan, children, childMap);
            }
        }

    }

    @GetMapping("/queryByRoot")
    public ProjectPlanViewVO[] queryByRoot(@RequestParam("rootId") String rootId) throws BusinessException {
        ProjectPlanViewVO[] allVOs = query.queryViewByRoot(rootId);
        if (ArrayUtils.isEmpty(allVOs)) {
            return allVOs;
        }
        Map<String, List<ProjectPlanViewVO>> childMap = genChildMap(allVOs);
        List<ProjectPlanViewVO> result = childMap.get(StringUtils.EMPTY);
        if (result == null) {
            return new ProjectPlanViewVO[0];
        } else {
            genCodeOfTree(null, result, childMap);
            return result.toArray(new ProjectPlanViewVO[0]);
        }
    }

    @GetMapping("/queryByPkPlan")
    public ProjectPlanViewVO queryByPkPlan(@RequestParam("pkPlan") String pkPlan) throws BusinessException {

        /**
         *  1. 通过pkPlan 查询ProjectPlan
         *  2. 在通过pkPlan查询反馈记录信息
         *  3. 在通过pkPlan 查询指标记录信息
         */

        ProjectPlanViewVO projectPlanViewVO = query.queryViewByPkPlan(pkPlan);
        return projectPlanViewVO;
    }

    @GetMapping("/queryLeafByRoot")
    public ProjectPlanViewVO[] queryLeafByRoot(@RequestParam("rootId") String rootId) throws BusinessException {
        return query.queryViewLeafByRoot(rootId);
    }

    @PostMapping("/updateProgresses")
    //@PMApprove
    public PlanWriteVO updatePlanProgresses(@RequestBody @Validated PlanWriteVO planWriteVO, BindingResult errors) throws BusinessException {
        if (errors.hasErrors()) {
            throw new IllegalRequestArgException();
        }
        return maintain.updatePlanProgressFull(planWriteVO);
    }

    @GetMapping("/progressHistory")
    public PlanProgressHistoryVO[] queryProgressHisByPlan(@RequestParam("planId") String planId) throws BusinessException {
        PlanProgressHistoryVO[] his = query.queryProgressHisByPlan(planId);
        if (!ArrayUtils.isEmpty(his)) {
            userInfoQuery.tranUserInfoField(his, new String[]{CommonFieldConst.CREATOR}, new String[]{CommonFieldConst.CREATOR_NAME});
        }
        return his;
    }

    @PostMapping("/delete")
    public int deletePlanRecursive(@RequestBody ProjectPlanVO plan, BindingResult errors) throws BusinessException {
        if (StringUtils.isEmpty(plan.getPkPlan())) {
            errors.rejectValue(ProjectPlanVO.PK_PLAN, null);
        }
        if (StringUtils.isEmpty(plan.getChangeFlag())) {
            errors.rejectValue(CommonFieldConst.CHANGE_FLAG, null);
        }
        if (errors.hasErrors()) {
            throw new IllegalRequestArgException();
        }
        maintain.deletePlan(plan.getPkPlan(), plan.getChangeFlag());
        return 1;
    }


    /**
     * 根据pkPlanWrite进行待办详情查询
     */
    @RequestMapping("/getDetailByPlanWriteId")
    public ProjectPlanViewVO[] getDetailByPlanWriteId(@RequestParam("pkPlanWrite") String pkPlanWrite) throws BusinessException {
        ProjectPlanViewVO[] allVOs = query.getPlanWriteById(pkPlanWrite);
        if (ArrayUtils.isEmpty(allVOs)) {
            return allVOs;
        }
        Map<String, List<ProjectPlanViewVO>> childMap = genChildMap(allVOs);

        List<ProjectPlanViewVO> result = childMap.get(StringUtils.EMPTY);
        if (result == null) {
            return new ProjectPlanViewVO[0];
        } else {
            genCodeOfTree(null, result, childMap);
            return result.toArray(new ProjectPlanViewVO[0]);
        }

    }

    //计算进度
    public void setProcess(ProjectPlanViewVO parent, List<ProjectPlanViewVO> tree) {
        if (tree == null || tree.isEmpty()) return;
        int childAvg = 0;
        int days = 0;
        for (ProjectPlanViewVO projectPlanViewVO : tree) {
            List<ProjectPlanViewVO> childList = projectPlanViewVO.getChild() == null ? new ArrayList<ProjectPlanViewVO>() : Arrays.asList(projectPlanViewVO.getChild());
            setProcess(projectPlanViewVO, childList);
            //因为默认结束时间为当天结束 所以天数+1
            int day = getDayDiffer(projectPlanViewVO.getExpeStartDate(), projectPlanViewVO.getExpeEndDate()) + 1;
            days += day;
            childAvg += projectPlanViewVO.getProgress() * day;
        }
        if (parent != null) parent.setProgress(childAvg / days);
    }

    public static int getDayDiffer(Date startDate, Date endDate) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        long startDateTime = 0, endDateTime = 0;
        try {
            startDateTime = dateFormat.parse(dateFormat.format(startDate)).getTime();
            endDateTime = dateFormat.parse(dateFormat.format(endDate)).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return (int) ((endDateTime - startDateTime) / (1000 * 3600 * 24));
    }

    /**
     * @param userId
     * @param parent
     * @param tree               树
     * @param projectPlanViewVOS 每个根节点可填报任务项结合
     * @param flag               是否所有的计划项负责人都为空 只有根节点有这个标志
     * @return 所有有可填报任务项的根计划
     */
    public List<ProjectPlanViewVO> getLastProjectPlanVO(String userId, ProjectPlanViewVO parent, List<ProjectPlanViewVO> tree, List<ProjectPlanViewVO> projectPlanViewVOS, boolean flag) {

        ArrayList<ProjectPlanViewVO> result = null;
        int n = 0;
        for (ProjectPlanViewVO projectPlanViewVO : tree) {
            List<ProjectPlanViewVO> childList = projectPlanViewVO.getChild() == null ? new ArrayList<ProjectPlanViewVO>() : Arrays.asList(projectPlanViewVO.getChild());
            if (projectPlanViewVO.getPkParent() == null) {
                //每个根节点创建一个末级节点集合
                projectPlanViewVOS = getLastProjectPlanVO(userId, projectPlanViewVO, childList, new ArrayList<ProjectPlanViewVO>(), projectPlanViewVO.getNoManagerFlag());
            } else {
                if (projectPlanViewVO.getManager() == null) projectPlanViewVO.setManager(parent.getManager());
                projectPlanViewVOS = getLastProjectPlanVO(userId, projectPlanViewVO, childList, projectPlanViewVOS, flag);
                if ((userId.equals(projectPlanViewVO.getManager()) || flag)
                        && projectPlanViewVO.getChild() == null) projectPlanViewVOS.add(projectPlanViewVO);
            }
            //找到符合数据的树 设置给根节点
            if (projectPlanViewVO.getPkParent() == null) {
                if (projectPlanViewVOS != null && !projectPlanViewVOS.isEmpty()) {
                    if (result == null) result = new ArrayList<>();
                    ProjectPlanViewVO tempProjectPlanViewVO = new ProjectPlanViewVO();
                    BeanUtils.copyProperties(projectPlanViewVO, tempProjectPlanViewVO);
                    tempProjectPlanViewVO.setChild(projectPlanViewVOS.toArray(new ProjectPlanViewVO[0]));
                    result.add(tempProjectPlanViewVO);
                }
                if (++n == tree.size()) projectPlanViewVOS = result;
            }
        }
        return projectPlanViewVOS;
    }

    /**
     * @param userId
     * @param parent
     * @param tree
     * @param projectPlanViewVOS 每个根节点可填报任务项结合
     * @param flag               是否所有的计划项负责人都为空 只有根节点有这个标志
     * @return 返回所有有权限的根节点和对应的权限树
     */
    public List<ProjectPlanViewVO> getProjectPlanVOTree(String userId, ProjectPlanViewVO parent, List<ProjectPlanViewVO> tree, List<ProjectPlanViewVO> projectPlanViewVOS, Boolean flag) {
        /**
         *  每个根节点找到对应的权限树就结束
         */
        ArrayList<ProjectPlanViewVO> result = null;
        int n = 0;
        for (ProjectPlanViewVO projectPlanViewVO : tree) {
            //当为数据且所有计划节点负责人为空时
            if (projectPlanViewVO.getPkParent() == null && projectPlanViewVO.getNoManagerFlag()) {
                if (result == null) result = new ArrayList<>();
                result.add(projectPlanViewVO);
                if (++n == tree.size()) projectPlanViewVOS = result;
                continue;
            }

            List<ProjectPlanViewVO> childList = projectPlanViewVO.getChild() == null ? new ArrayList<ProjectPlanViewVO>() : Arrays.asList(projectPlanViewVO.getChild());
            if (projectPlanViewVO.getPkParent() == null) projectPlanViewVOS = new ArrayList<ProjectPlanViewVO>();

            if (userId.equals(projectPlanViewVO.getManager())) {
                projectPlanViewVOS.add(projectPlanViewVO);
            } else {
                if (projectPlanViewVO.getManager() == null)
                    projectPlanViewVO.setManager(parent == null ? null : parent.getManager());
                projectPlanViewVOS = (ArrayList<ProjectPlanViewVO>) getProjectPlanVOTree(userId, projectPlanViewVO, childList, projectPlanViewVOS, true);
            }

            //找到符合数据的树 设置给根节点
            if (projectPlanViewVO.getPkParent() == null) {
                if (projectPlanViewVOS != null && !projectPlanViewVOS.isEmpty()) {
                    if (result == null) result = new ArrayList<>();
                    ProjectPlanViewVO tempProjectPlanViewVO = new ProjectPlanViewVO();
                    BeanUtils.copyProperties(projectPlanViewVO, tempProjectPlanViewVO);
                    tempProjectPlanViewVO.setChild(projectPlanViewVOS.toArray(new ProjectPlanViewVO[0]));
                    result.add(tempProjectPlanViewVO);
                }
                if (++n == tree.size()) projectPlanViewVOS = result;
            }
        }
        return projectPlanViewVOS;
    }

    /**
     * 每个根节点设置 是否所有任务项没有负责人
     *
     * @param finalProjectPlanViewVO 跟节点
     * @param tree                   树
     */
    public void setNoManagerFlag(ProjectPlanViewVO finalProjectPlanViewVO, List<ProjectPlanViewVO> tree) {
        for (ProjectPlanViewVO projectPlanViewVO : tree) {
            List<ProjectPlanViewVO> childList = projectPlanViewVO.getChild() == null ? new ArrayList<ProjectPlanViewVO>() : Arrays.asList(projectPlanViewVO.getChild());
            if (projectPlanViewVO.getPkParent() == null) setNoManagerFlag(projectPlanViewVO, childList);
            else {
                setNoManagerFlag(finalProjectPlanViewVO, childList);
                if (projectPlanViewVO.getManager() != null && !StringUtils.isEmpty(projectPlanViewVO.getManager())) {
                    finalProjectPlanViewVO.setNoManagerFlag(false);
                }
            }
        }
    }
}
